package org.oslims.client.uicomponents;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;

public class StyleableFlexTable extends FlexTable {

	private class SortEntry implements Comparable<SortEntry> {

		private Integer rowIndex;
		private String fieldValue;
		private List<Widget> rowData = new ArrayList<Widget>();

		public String getFieldValue() {
			return fieldValue;
		}

		public void setFieldValue(String fieldValue) {
			this.fieldValue = fieldValue;
		}

		public void setRowIndex(Integer rowIndex) {
			this.rowIndex = rowIndex;
		}

		@SuppressWarnings("unused")
		public Integer getRowIndex() {
			return rowIndex;
		}

		@Override
		public int compareTo(SortEntry arg0) {
			return this.getFieldValue().compareTo(arg0.getFieldValue());
		}

		public String toString() {
			return this.rowIndex + " - " + this.fieldValue;
		}

		public List<Widget> getRowData() {
			return rowData;
		}
	}

	public StyleableFlexTable() {
		super();
		super.addStyleName("FlexTable");

		super.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				Cell c = getCellForEvent(event);
				if (c.getRowIndex() == 0) {

					HTML uppArrow = new HTML();
					uppArrow.setHTML("&uarr;");

					HTML downArrow = new HTML();
					downArrow.setHTML("&darr;");

					Boolean sortDesc = false;
					Label headerLabel = (Label) getWidget(0, c.getCellIndex());

					if (headerLabel.getElement().getInnerHTML().contains(uppArrow.getHTML())) {
						sortDesc = true;
					}

					for (int i = 0; i < getCellCount(0); i++) {
						Label l = (Label) getWidget(0, i);
						if (l != null) {
							l.getElement().setInnerHTML(l.getElement().getInnerHTML().replace(uppArrow.getHTML(), ""));
							l.getElement().setInnerHTML(l.getElement().getInnerHTML().replace(downArrow.getHTML(), ""));
						}
					}

					if (sortDesc) {
						headerLabel.getElement().setInnerHTML(headerLabel.getElement().getInnerHTML() + downArrow.getHTML());
					} else {
						headerLabel.getElement().setInnerHTML(headerLabel.getElement().getInnerHTML() + uppArrow.getHTML());
					}

					sortRows(c.getCellIndex(), sortDesc);
				}
			}
		});
	}

	protected void sortRows(int colIndex, Boolean sortDesc) {

		List<SortEntry> sortEntries = new ArrayList<SortEntry>();

		for (int i = 1; i < getRowCount(); i++) {
			SortEntry e = new SortEntry();
			e.setFieldValue(getText(i, colIndex));
			e.setRowIndex(i);

			for (int j = 0; j < getCellCount(i); j++) {
				e.getRowData().add(getWidget(i, j));
			}

			sortEntries.add(e);
		}

		Collections.sort(sortEntries);

		if (sortDesc) {
			Collections.reverse(sortEntries);
		}

		// Clear the table
		while (getRowCount() > 2) {
			removeRow(1);
		}

		for (int i = 0; i < sortEntries.size(); i++) {
			SortEntry se = sortEntries.get(i);

			for (int j = 0; j < se.getRowData().size(); j++) {
				setWidget(i + 1, j, se.getRowData().get(j));
				applyStyle(i + 1, j);
			}
		}
	}

	public void setWidget(int rowIndex, int colIndex, Widget cellWidget) {
		super.setWidget(rowIndex, colIndex, cellWidget);
		applyStyle(rowIndex, colIndex);
	}

	public void setText(int rowIndex, int colIndex, String cellText) {
		super.setWidget(rowIndex, colIndex, new Label(cellText));
		applyStyle(rowIndex, colIndex);
	}

	private void applyStyle(int rowIndex, int colIndex) {
		if (rowIndex == 0) {
			super.getCellFormatter().addStyleName(rowIndex, colIndex, "FlexTable-ColumnLabelCell");
			super.getRowFormatter().addStyleName(rowIndex, "FlexTable-ColumnLabel");
		} else {
			super.getCellFormatter().addStyleName(rowIndex, colIndex, "FlexTable-DataCell");

			if (rowIndex % 2 == 0) {
				super.getRowFormatter().removeStyleName(rowIndex, "FlexTable-EvenRow");
				super.getRowFormatter().addStyleName(rowIndex, "FlexTable-OddRow");
			} else {
				super.getRowFormatter().removeStyleName(rowIndex, "FlexTable-OddRow");
				super.getRowFormatter().addStyleName(rowIndex, "FlexTable-EvenRow");
			}
		}
	}
}
